﻿using System;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Net.Http;

namespace TestThread
{
    class Program
    {
        static readonly Random s_rnd = new Random();
        static async Task Main(string[] args)
        {
            // Method1();
            // Method2();
            //Method3();
            //Method4();
            //Method5();
            //Method6();            
            // Method7();
            //int nLen = await GetUrlContentLengthAsync();
            //Task.Run(() => GetUrlContentLengthAsync());
            //Console.WriteLine($"Completed TotalSize:{nLen}");
            //await DisplayCurrentInfo();
            Console.WriteLine($"You rolled {await GetDiceRollAsync()}");

            //Method8();
            Console.Read();
        }
        #region Task使用【1】几种启动方式
        static void Method1()
        {
            Task task1 = new Task(() =>
              {
                  //在这里写要具体干的事
                  Console.WriteLine($"Task1开启的线程ID={Thread.CurrentThread.ManagedThreadId}");

              });
            task1.Start();//适合线程开启和执行是分开的情况
            Console.WriteLine("----------------------");
            Console.Read();
            //Task=Thraed+ThreadPool

        }
        static void Method2()
        {
            Task task1 = Task.Run(() =>
            {
                //在这里写要具体干的事
                Console.WriteLine($"Task1开启的线程ID={Thread.CurrentThread.ManagedThreadId}");

            });            
            Console.WriteLine("----------------------");
            Console.Read();
            //Task=Thraed+ThreadPool

        }
        static void Method3()
        {
            Task task1 = Task.Factory.StartNew(() =>
            {
                //在这里写要具体干的事
                Console.WriteLine($"Task1开启的线程ID={Thread.CurrentThread.ManagedThreadId}");

            });
            Console.WriteLine("----------------------");
            Console.Read();
            //Task=Thraed+ThreadPool

        }
        #endregion
        #region Task使用【2】几种阻塞方式和任务延续
        static void Method4()
        {
            Task task1 = new Task(() =>
            {
                //在这里写要具体干的事
                Thread.Sleep(1000);
                Console.WriteLine($"Task1开启的线程ID={Thread.CurrentThread.ManagedThreadId}{DateTime.Now.ToLongTimeString()}");

            });
            task1.Start();
            Task task2 = new Task(() =>
            {
                //在这里写要具体干的事
                Thread.Sleep(3000);
                Console.WriteLine($"Task2开启的线程ID={Thread.CurrentThread.ManagedThreadId}{DateTime.Now.ToLongTimeString()}");

            });
            
            task2.Start();
            //逐个等待 执行顺序:task1->task2->mainTask
            //task1.Wait();
            //task2.Wait();
            //换一个方式和上述方式一致
            //Task.WaitAll(task1, task2);
            //第三种方式
            Task.WaitAny(task1, task2); //执行顺序: task1->mainTask->task2

            Console.WriteLine("----------------------");
            Console.Read();
           

        }

        #endregion
        #region Task使用【3】正确地终止线程
        static void Method5()
        {
            //定义一个信号源
            CancellationTokenSource cts = new CancellationTokenSource();

            Task task1 = Task.Factory.StartNew(() =>
            {
                while (!cts.IsCancellationRequested)
                {
                    //在这里写要具体干的事
                    Thread.Sleep(200);
                    Console.WriteLine($"ThreadID={Thread.CurrentThread.ManagedThreadId}");
                }


            },cts.Token);
            //注册一个委托，该委托在任务取消后执行
            cts.Token.Register(() =>
            {
                //Thread.Sleep(500);
                Console.WriteLine("--Task已经取消--");
            });
            Thread.Sleep(2000);
            cts.Cancel();//取消任务
            Console.WriteLine("----------------------");
            Console.Read();
        }
        #endregion
        #region 测试async（无返回值）
        static void Method6()
        {
            Console.WriteLine("Start");
            GetValueAsync();
            //异步执行，直接执行下面的语句
            Console.WriteLine("End");
            Console.Read();


        }

        public static async Task GetValueAsync()
        {
            await Task.Run(() =>
            {
                Thread.Sleep(1000);
                for (int i = 0; i < 5; ++i)
                {
                    Console.WriteLine($"From Task:{i}");
                }

            });
            //await组塞点，以上执行完后，再执行下面的Task End
            Console.WriteLine("Task End");
        }
        #endregion
        #region async（返回值）
        static async  void Method7()
        {
            int count;
            Console.WriteLine("Main Thread----Begin");
            count =await Task<int>.Run(GetAsyncRes);
            Console.WriteLine($"Thread Call Res={count}");
            Console.WriteLine("Main Thread----End");
        }
        static async Task<int> GetAsyncRes()
        {
            int count = 0;
            await Task.Run(() =>
            {
                for(int i = 0; i <= 100; i++)
                {
                    count += i;
                }
            });
            return count;
        }
        static  void Method8()
        {
            var html = GetResult();

            Console.WriteLine("稍等... 正在下载 cnblogs -> html \r\n");

            var content = html.Result;
            Console.WriteLine("OK... 下载 cnblogs -> html 完成\r\n");
            Console.Read();

            Console.WriteLine(content);
        }
        static async Task<string> GetResult()
        {
            var client = new WebClient();

            var content = await client.DownloadStringTaskAsync(new Uri("http://cnblogs.com"));

            return content;
        }
        #endregion

        static async Task<int> GetUrlContentLengthAsync()
        {
            var client = new HttpClient();

            Task<string> getStringTask =
                client.GetStringAsync("https://docs.microsoft.com/dotnet");

            DoIndependentWork();

            string contents = await getStringTask;
            Console.WriteLine("Get...");

            return contents.Length;
        }
        static void DoIndependentWork()
        {
            Console.WriteLine("Working...");
        }
        static async Task DisplayCurrentInfo()
        {

            await WaitAndApologizeAsync();

            Console.WriteLine($"Today is {DateTime.Now:D}");
            Console.WriteLine($"The current time is {DateTime.Now.TimeOfDay:t}");
            Console.WriteLine("The current temperature is 76 degrees.");
        }

        static async Task WaitAndApologizeAsync()
        {
            await Task.Delay(2000);

            Console.WriteLine("Sorry for the delay...\n");
        }
        static async ValueTask<int> GetDiceRollAsync()
        {
            Console.WriteLine("Shaking dice...");

            int roll1 = await RollAsync();
            int roll2 = await RollAsync();

            return roll1 + roll2;
        }

        static async ValueTask<int> RollAsync()
        {
            await Task.Delay(500);

            int diceRoll = s_rnd.Next(1, 7);
            return diceRoll;
        }
    }
}
